package site.tuluan.sp4j.common.core.component.token;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import site.tuluan.sp4j.common.core.component.cache.ICache;
import site.tuluan.sp4j.common.core.domain.LoginUser;
import site.tuluan.sp4j.common.utils.JwtUtils;
import site.tuluan.sp4j.common.utils.StringUtils;

import javax.annotation.Resource;
import java.util.Map;

@Component
public class TokenService {
    private static final Logger log = LoggerFactory.getLogger(TokenService.class);

    /**
     * 用户缓存前缀
     */
    private static final String USER_PREFIX = "user:";

    /**
     * key:uuid
     */
    private static final String UUID = "uuid";

    @Resource
    private ICache cache;

    /**
     * 生成token
     * @param payloadMap 载荷
     * @param loginUser 登录用户信息
     * @param secret 密钥
     * @param timeout 过期时长，单位秒
     * @return 生成的token
     */
    public String geneToken(Map<String, String> payloadMap, LoginUser loginUser, String secret, int timeout) {
        String uuid = StringUtils.geneUUID();
        if (!payloadMap.containsKey(UUID)) {
            payloadMap.put(UUID, uuid);
        }

        String token = JwtUtils.geneToken(payloadMap, secret, timeout);

        // 将登录信息添加到缓存中
        loginUser.setToken(token);
        cache.setCache(USER_PREFIX + uuid, loginUser, timeout);

        return token;
    }

    /**
     * 验证token
     * @param token token
     * @return 是否通过
     */
    public boolean verifyToken(String token) {
        // 未从redis里获取到已登录用户信息，验证失败
        LoginUser loginUser;
        try {
            loginUser = getLoginUser(token);
            if (loginUser == null) {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
        // 已登录用户信息里token与待验证token不一致，验证失败
        if (!loginUser.getToken().equals(token)) {
            return false;
        }
        // token自身验证失败，验证失败
        if (!JwtUtils.verifyToken(token, loginUser.getSysUser().getPassword())) {
            return false;
        }

        return true;
    }

    /**
     * 验证token
     * @param token token
     * @param loginUser 已登录用户
     * @return 是否通过
     */
    public boolean verifyToken(String token, LoginUser loginUser) {
        // 已登录用户信息为空，验证失败
        if (loginUser == null) {
            return false;
        }
        // 已登录用户信息里token与待验证token不一致，验证失败
        if (!loginUser.getToken().equals(token)) {
            return false;
        }
        // token自身验证
        return JwtUtils.verifyToken(token, loginUser.getSysUser().getPassword());
    }

    /**
     * 获取已登录用户信息
     * @param token token
     * @return 已登录用户信息
     */
    public LoginUser getLoginUser(String token) {
        String uuid;
        try {
            uuid = JwtUtils.getClaimStr(token, UUID);
        } catch (Exception e) {
            log.error("用户TOKEN验证失败", e);
            throw new TokenException("用户TOKEN验证失败", e);
        }

        return cache.getCache(USER_PREFIX + uuid);
    }

    /**
     * 清除用户登录信息
     * @param token token
     * @return 结果
     */
    public boolean cleanLoginUser(String token) {
        String uuid;
        try {
            uuid = JwtUtils.getClaimStr(token, UUID);
        } catch (Exception e) {
            log.error("用户TOKEN验证失败", e);
            throw new TokenException("用户TOKEN验证失败", e);
        }

        return cache.removeCache(USER_PREFIX + uuid);
    }
}
